<template>
  <div class="task-manage-wrap">
    <ContentWrap>
      <div class="flex gap-10">
        <div
          class="flex flex-1 items-center justify-center"
          v-for="(item, index) in props.type === 'exit' ? exitNavList : navList"
          :key="'nav' + index"
          :class="{ 'vertical-line': [1, 3, 6].includes(index) }"
        >
          <div class="flex-1">
            <div class="text-point text-13px color-#909399">{{ item.title }}</div>
            <div class="ml-10px text-20px font-bold color-#5F6266">{{ item.val }}</div>
          </div>
        </div>
      </div>
    </ContentWrap>
    <ContentWrap>
      <el-form @submit.prevent ref="formRef" :model="formOption">
        <el-row>
          <el-col :span="6">
            <el-form-item class="mx-5" label="任务名称" prop="name">
              <ns-input
                placeholder="请输入任务名称"
                v-model="formOption.name"
                clearable
                :maxlength="50"
              />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item class="mx-5" label="任务类型" prop="typeSelect">
              <el-select placeholder="请选择任务类型" v-model="formOption.typeSelect" clearable>
                <el-option
                  :label="item.value"
                  :value="item.key"
                  :key="item.value"
                  v-for="item in taskTypeList"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item class="mx-5" label="扫描频率" prop="scanMethod">
              <el-select placeholder="请选择扫描频率" v-model="formOption.scanMethod" clearable>
                <el-option
                  :label="item"
                  :value="key"
                  :key="'scanMethod' + key"
                  v-for="(item, key) in taskData.scanMethodList"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item class="mx-5" label="任务状态" prop="status">
              <el-select placeholder="请选择任务状态" v-model="formOption.status" clearable>
                <el-option
                  :label="item"
                  :value="key"
                  :key="'status' + key"
                  v-for="(item, key) in taskData.statusList"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item class="mx-5" label="创建人" prop="creator">
              <el-select
                placeholder="请选择创建人"
                v-model="formOption.creator"
                clearable
                filterable
              >
                <el-option
                  :label="item.username + '（' + item.nickname + '）'"
                  :value="item.id"
                  :key="item.id"
                  v-for="item in taskData.userList"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item class="mx-5" label="数据源名称" prop="datasourceName">
              <ns-input
                placeholder="请输入数据源名称"
                v-model="formOption.datasourceName"
                clearable
              />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item class="mx-5" label="资产类型" prop="assetType">
              <el-select placeholder="请选择资产类型" v-model="formOption.assetType" clearable>
                <el-option
                  v-for="item in assetTypeList"
                  :label="item.showName"
                  :key="item.name"
                  :value="item.name"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item class="mx-5" label="IP" prop="ip">
              <ns-input placeholder="请输入ip" v-model="formOption.ip" clearable />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="6">
            <el-form-item class="mx-5" label="最近执行时间" prop="startTime">
              <el-date-picker
                v-model="formOption.startTime"
                type="datetimerange"
                range-separator="到"
                start-placeholder="开始日期"
                end-placeholder="结束日期"
                format="YYYY-MM-DD HH:mm:ss"
                value-format="YYYY-MM-DD HH:mm:ss"
              />
            </el-form-item>
          </el-col>
          <el-col v-if="type === 'exit'" :span="6">
            <el-form-item class="mx-5" label="出境批次" prop="batchNum">
              <ns-input placeholder="请选择出境批次" v-model="formOption.batchNum" clearable />
            </el-form-item>
          </el-col>
          <el-col :span="type === 'exit' ? 12 : 18" class="text-right">
            <el-button
              type="primary"
              @click="query"
              v-hasPermi="[`asset:assetDiscovery-taskManage:search-${props.type}`]"
              >搜索</el-button
            >
            <el-button @click="resetSearch"> 重置 </el-button>
          </el-col>
        </el-row>
      </el-form>
    </ContentWrap>
    <ContentWrap>
      <div class="mb-16px">
        <el-button
          v-if="type !== 'exit'"
          type="primary"
          @click="addTask('DataSource')"
          v-hasPermi="['asset:assetDiscovery-taskManage:DatasourceCreate']"
        >
          创建数据源探测任务
        </el-button>
        <el-button
          type="primary"
          @click="addTask('DataCollect', 'db')"
          v-hasPermi="[`asset:assetDiscovery-taskManage:DBCollect-${props.type}`]"
        >
          创建数据库采集任务
        </el-button>
        <el-button
          type="primary"
          @click="addTask('DataCollect', 'file')"
          v-hasPermi="[`asset:assetDiscovery-taskManage:FileCollect-${props.type}`]"
        >
          创建文件服务器采集任务
        </el-button>
        <el-button
          type="primary"
          v-if="type == 'exit'"
          @click="addTask('FileAnalysis')"
          v-hasPermi="[`asset:assetDiscovery-taskManage:FileAnalysisCreate-${props.type}`]"
        >
          创建文件分析任务
        </el-button>

        <el-button
          :disabled="disabledDelRows"
          type="danger"
          @click="batchDelRow"
          v-hasPermi="[`asset:assetDiscovery-taskManage:batchDelete-${props.type}`]"
        >
          删除
        </el-button>
      </div>
      <AsyncTable
        ref="tableRef"
        :cell-class-name="setCellClass"
        :columns="columns"
        :fetchData="fetchData"
        :auto-request="false"
        @selection-change="handleSelectionChange"
      />
    </ContentWrap>
  </div>
</template>
<script lang="tsx" setup>
import { ref, reactive, getCurrentInstance } from 'vue'
import { ElMessage } from 'element-plus'
import { useRoute, useRouter } from 'vue-router'
import { Loading } from '@element-plus/icons-vue'
import ExpandDetail from './expandDetail.vue'
import * as api from '@/api/asset/taskManage'
import { handleTree } from '@/utils/tree'
import * as UserApi from '@/api/system/user'
import { getSimpleDeptList } from '@/api/system/dept'
import { getAssetTypeList } from '@/api/dataSourceManage/index'
import { getStatistics, getTaskList, TaskVO } from '@/api/asset/taskManage/index'
import { collectTaskList } from '@/api/asset/taskManage/dataCollect'

// import { getTaskList } from './mock.js'
const message = useMessage() // 消息弹窗

defineOptions({ name: 'TaskManage' })
const props = defineProps({
  type: {
    type: String,
    default: 'task'
  }
})

const { proxy } = getCurrentInstance() as any
const router = useRouter()
const assetTypeList = ref([])
const navList = ref([
  { title: '扫描任务总数', val: 0 },
  { title: '单次扫描任务数', val: 0 },
  { title: '定期扫描任务数', val: 0 },
  { title: '数据源探测任务数', val: 0 },
  { title: '数据采集任务数', val: 0 },
  { title: '近一月执行任务数', val: 0 }
])
const exitNavList = ref([
  { title: '扫描任务总数', val: 0 },
  { title: '单次扫描任务数', val: 0 },
  { title: '定期扫描任务数', val: 0 },
  { title: '数据采集任务数', val: 0 },
  { title: '近一月执行任务数', val: 0 }
])
const formRef = ref()
const deptList = ref<Tree[]>([]) // 树形结构
const taskData = reactive({
  scanMethodList: {
    1: '单次扫描',
    2: '定期扫描'
  },
  exitBatchList: [],
  userList: [],
  cascaderProps: {
    checkStrictly: true,
    label: 'name',
    value: 'id',
    children: 'children'
  },
  statusList: {
    1: '待启动',
    2: '进行中',
    3: '暂停',
    4: '失败',
    5: '成功',
    6: '停止'
  },
  ids: []
})
const disabledDelRows = ref(true)
const btnsVerify = {
  1: '10001',
  2: '01100',
  3: '00010',
  4: '10001',
  5: '10001',
  6: '10001'
}

const statusColor = {
  1: '',
  2: '#409EFF',
  3: '#E6A23C',
  4: '#F56C6C',
  5: '#67C23A',
  6: '#E6A23C'
}
const taskTypeList = computed(() => {
  return props.type === 'exit'
    ? [{ key: 4, value: '数据库采集' }]
    : [
        { key: 1, value: '数据源探测' },
        { key: 2, value: '数据库采集' },
        { key: 3, value: '文件服务器采集' }
      ]
})
const columns = computed(() => {
  const baseColumns = [
    { type: 'selection', width: 30 },
    {
      type: 'expand',
      label: '',
      width: 30,
      render: ({ row }) => getDetail(row)
    },
    { label: '任务名称', prop: 'name', 'min-width': 100, 'show-overflow-tooltip': true },
    {
      label: '任务类型',
      width: 140,
      'show-overflow-tooltip': true,
      formatter: function (row) {
        if (row.taskType === 1) {
          return '数据源探测'
        } else if ([2, 4].includes(row.taskType)) {
          return '数据库采集'
        } else if ([3, 5].includes(row.taskType)) {
          return '文件服务器采集'
        } else if (row.taskType === 6) {
          return '文件分析'
        }
      }
    },
    {
      label: '出境批次',
      prop: 'batchNum',
      'min-width': 100,
      'show-overflow-tooltip': true,
      hide: props.type === 'task'
    },
    {
      label: '执行进度',
      'min-width': 120,
      render: ({ row }) => <el-progress percentage={parseFloat(row.progress)} />
    },
    {
      label: '状态',
      width: 115,
      'show-overflow-tooltip': true,
      render: ({ row }) => {
        return row.status == 4 ? (
          <el-tooltip
            class="box-item"
            effect="dark"
            content={row?.failReason || '无'}
            placement="top"
          >
            <span style={{ color: statusColor[row.status] }}>
              {taskData.statusList[row.status]}
            </span>
          </el-tooltip>
        ) : (
          <>
            <span style={{ color: statusColor[row.status] }}>
              {taskData.statusList[row.status]}
            </span>
            {row.status == 2 ? (
              <el-icon class="el-icon is-loading" style="vertical-align:-3px;margin-left: 5px;">
                <Loading />
              </el-icon>
            ) : (
              ''
            )}
          </>
        )
      }
    },
    {
      label: '扫描频率',
      width: 160,
      formatter: (row) => filterScanMethod(row)
    },
    {
      label: '归属机构',
      prop: 'department',
      width: 160
    },
    {
      label: '归属系统',
      prop: 'system',
      width: 160
    },
    { prop: 'creatorName', label: '创建人', width: 80, 'show-overflow-tooltip': true },
    {
      prop: 'latestScanTime',
      label: '最近执行时间',
      'min-width': 170,
      'show-overflow-tooltip': true
    },
    {
      label: '操作项',
      fixed: 'right',
      width: 230,
      render: ({ row }) => {
        return (
          <div class="operate-btn">
            <el-button
              type="primary"
              size="small"
              text
              onClick={() => toRoute(row)}
              v-HasPermi={[[`asset:assetDiscovery-taskManage:Result-${props.type}`]]}
            >
              查看结果
            </el-button>

            {isShowBtns(row)}
            <ns-button
              size="small"
              confirm
              text
              type="danger"
              onClick={() => delRow(row)}
              v-HasPermi={[[`asset:assetDiscovery-taskManage:singleDelete-${props.type}`]]}
            >
              删除
            </ns-button>
          </div>
        )
      }
    }
  ]
  return baseColumns
})
const tableRef = ref()
const allSelect = ref(false)
const dept = ref([])
const renewComponent = ref(0) //父组件同步刷新子组件
let preTableData = []
const formOption = reactive({
  name: '',
  typeSelect: null,
  scanMethod: '',
  status: '',
  deptId: '',
  creator: '',
  datasourceName: '',
  assetType: '',
  ip: '',
  startTime: [],
  batchNum: ''
})

function getDetail(row: TaskVO) {
  return <ExpandDetail renewComponent={renewComponent.value} id={row.id} />
}

function setCellClass({ row, column }) {
  if (column.type === 'expand' && ![2, 4].includes(row.type)) {
    return 'hide-expand'
  }
}

function addTask(type: string, dataType?: string) {
  const affaix = props.type === 'exit' ? 'Exit' : ''
  router.push({ path: `/asset/add${type}Task${affaix}`, query: { dataType } })
}
async function allSelectHandle() {
  allSelect.value = !allSelect.value
  tableRef.value.ignorePageSelect(allSelect.value)
}
let timer: number | null = null
const runtime = () => {
  clearTimeout(timer)
  timer = setTimeout(async () => {
    const isRunning = preTableData.some((item: any) => item.status == 2)
    if (isRunning) {
      tableRef.value.currentPageReload()
      ++renewComponent.value
    }
  }, 6000)
}
async function fetchData({ page, pageSize }) {
  if (dept.value && dept.value.length > 0) {
    formOption.deptId = dept.value[dept.value.length - 1]
  } else {
    formOption.deptId = ''
  }
  let data = {
    ...formOption,
    type: props.type === 'exit' ? [4, 5] : [1, 2, 3],
    batchNum: formOption.batchNum || '',
    pageSize: pageSize,
    page: page
  }
  const res = await getTaskList(data)
  preTableData = res.data
  runtime()
  getNavList()

  return {
    data: res.data,
    count: res.count
  }
}
const scanCycleList = reactive({
  month: '每月',
  week: '每周',
  day: '每日'
})
const scanCycleUnit = reactive({
  '1': '一',
  '2': '二',
  '3': '三',
  '4': '四',
  '5': '五',
  '6': '六',
  '7': '日'
})
const filterScanMethod = (row) => {
  if (row.scanMethod === 1) {
    switch (row.execMethod) {
      case 1:
        return '单次-立即执行'
      case 2:
        return '单次-定时执行'
      case 3:
        return `单次-${row.execTime}`
    }
  } else if (row.scanMethod === 2) {
    const hour = row.execTime?.split(' ')[1]
    const cycle = `定期-${scanCycleList[row.detectionCycle]}`
    const date = `${row.detectionCycle == 'day' ? '' : row.detectionCycle == 'week' ? scanCycleUnit[row.detectionCycleNum] : row.detectionCycleNum}`
    const time = `${row.detectionCycle == 'month' ? '号' : ''} ${hour}`
    return cycle + date + time
  }
}

const isShowBtns = (row: TaskVO) => {
  let ver = btnsVerify[row.status]
  return (
    <>
      {Number(ver[0]) ? (
        <el-button
          size="small"
          text
          onClick={() => operationRow('start', row)}
          v-HasPermi={[[`asset:assetDiscovery-taskManage:operate-${props.type}`]]}
        >
          开始
        </el-button>
      ) : (
        ''
      )}
      {Number(ver[2]) ? (
        <el-button
          size="small"
          text
          onClick={() => operationRow('pause', row)}
          v-HasPermi={[[`asset:assetDiscovery-taskManage:operate-${props.type}`]]}
        >
          暂停
        </el-button>
      ) : (
        ''
      )}
      {Number(ver[1]) ? (
        <el-button
          size="small"
          text
          onClick={() => operationRow('stop', row)}
          v-HasPermi={[[`asset:assetDiscovery-taskManage:operate-${props.type}`]]}
        >
          停止
        </el-button>
      ) : (
        ''
      )}
      {Number(ver[3]) ? (
        <el-button
          size="small"
          text
          onClick={() => operationRow('resume', row)}
          v-HasPermi={[[`asset:assetDiscovery-taskManage:operate-${props.type}`]]}
        >
          继续
        </el-button>
      ) : (
        ''
      )}
      {Number(ver[4]) ? (
        <el-button
          size="small"
          text
          onClick={() => editRow(row)}
          v-HasPermi={[[`asset:assetDiscovery-taskManage:edit-${props.type}`]]}
        >
          编辑
        </el-button>
      ) : (
        ''
      )}
    </>
  )
}
function handleSelectionChange(rows) {
  disabledDelRows.value = !rows.length
  taskData.ids = rows.map((item) => item.id)
}
function batchDelRow() {
  proxy.$modal
    .confirm(`确定要删除选择的任务吗？`)
    .then(() => {
      api
        .deleteData({
          idList: taskData.ids,
          allSelect: allSelect.value
        })
        .then(({ code, message }) => {
          if (code === 200) {
            tableRef.value.fetchData()
            ElMessage.success('删除成功')
            getNavList()
          } else {
            ElMessage.error(message)
          }
        })
    })
    .catch(() => {})
}
function delRow(row: TaskVO) {
  api.deleteData({ idList: [row.id] }).then(({ code, message }) => {
    if (code === 200) {
      tableRef.value.fetchData()
      ElMessage.success('删除成功')
      getNavList()
    } else {
      ElMessage.error(message)
    }
  })
}
function editRow(row: TaskVO) {
  let type
  if (row.type === 1) {
    type = 'DataSource'
  } else if ([2, 4].includes(row.type)) {
    type = 'DataCollect'
  } else {
    type = 'FileAnalysis'
  }
  const affaix = props.type === 'exit' ? 'Exit' : ''
  router.push(
    `/asset/add${type}Task${affaix}?id=${row.id}&dataType=${row.taskType === 2 || row.taskType === 4 ? 'db' : 'file'}&jumpType=${row.jumpType ? row.jumpType : ''}&affaix=${props.type === 'exit' ? 'exit' : ''}`
  )
}
function query() {
  tableRef.value.resetPage()
  tableRef.value.fetchData()
  ++renewComponent.value
}
function resetSearch() {
  dept.value = []
  formRef.value.resetFields()
  query()
}

const toRoute = async (row: TaskVO) => {
  let type
  if (row.type === 1) {
    type = 'dataSource'
  } else if ([2, 4].includes(row.type)) {
    type = 'dataCollect'
    const detail = await getChildren(row)
    if (detail.count === 1) {
      viewResult(row, detail.data)
      return
    }
  } else {
    type = 'fileAnalysis'
  }

  const affaix = props.type === 'exit' ? 'Exit' : ''
  router.push({
    path: `/asset/${type}TaskResult${affaix}`,
    query: {
      id: row.id,
      execTime: row.execTime,
      latestHistoryId: row.latestHistoryId,
      dataType: row.taskType === 2 ? 'db' : 'file',
      jumpType: row.jumpType ? row.jumpType : ''
    }
  })
}

const viewResult = (row, children) => {
  router.push({
    path: `/asset/${children.datasourceType === 1 ? 'dataBaseResult' : 'fileServerResult'}`,
    query: {
      taskId: row.id,
      collectionAssetId: children.id,
      datasourceId: children.datasourceId,
      datasourceType: children.datasourceType
    }
  })
}

const getChildren = async (row) => {
  const { data, count } = await collectTaskList({ page: 1, pageSize: 10, taskId: row.id })
  return { data: data[0], count }
}

async function operationRow(key: string, row: TaskVO) {
  api.operation({ taskId: row.id, operation: key }).then((response) => {
    tableRef.value.fetchData()
    if (key === 'start' || key === 'resume') {
      ++renewComponent.value
    }
    message.success(response.message || '操作成功')
  })
}

async function getNavList() {
  const data = await getStatistics({
    type: props.type === 'exit' ? [4, 5] : [1, 2, 3]
  })
  if (props.type === 'exit') {
    exitNavList.value[0].val = data.allTaskNum || 0
    exitNavList.value[1].val = data.oneScanTaskNum || 0
    exitNavList.value[2].val = data.cycleScanTaskNum || 0
    exitNavList.value[3].val = data.scanTaskNum || 0
    exitNavList.value[4].val = data.nearlyAMonthTaskNum || 0
    // exitNavList.value[5].val = data.nearlyAMonthTaskNum || 0
  } else {
    navList.value[0].val = data.allTaskNum || 0
    navList.value[1].val = data.oneScanTaskNum || 0
    navList.value[2].val = data.cycleScanTaskNum || 0
    navList.value[3].val = data.discoverTaskNum || 0
    navList.value[4].val = data.scanTaskNum || 0
    navList.value[5].val = data.nearlyAMonthTaskNum || 0
  }
}

async function getDeptList() {
  const data = await getSimpleDeptList()
  deptList.value = data
}

async function initData() {
  getNavList()
  getDeptList()
  query()
  // 加载用户列表
  const userList = await UserApi.getSimpleUserList()
  taskData.userList = userList
}

onActivated(() => {
  initData()
})
onMounted(() => {
  initData()
  getAssetTypeList({ datasourceType: null }).then((res) => {
    assetTypeList.value = res
  })
})
onDeactivated(() => {
  clearTimeout(timer)
})
</script>
<style lang="scss" scoped>
.task-manage-wrap {
  .vertical-line::before {
    content: ' ';
    display: inline-block;
    border-right: 1px solid #ebebeb;
    height: 50px;
    margin-left: -30px;
    margin-right: 30px;
  }
  .text-point::before {
    content: '';
    display: inline-block;
    width: 6px;
    height: 6px;
    vertical-align: middle;
    background: #0f72e6;
    border-radius: 100%;
    margin-right: 5px;
  }
  .el-form .el-select {
    width: 100%;
  }
  :deep(.hide-expand .cell) {
    display: none;
  }
  :deep(.el-form .el-cascader) {
    width: 100%;
  }
  :deep(.operate-btn .el-button.is-text) {
    padding: 0 10px 0 0;
  }
}
</style>
